package cn.demoncat.util.sec;

import cn.demoncat.util.lang.msg.SecMsg;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;

/**
 * 
 * 
 * 描述：RC2 对称加密(单密钥算法，密钥可用于加密解密)
 *
 * @author yxl
 *
 * @version 2.0
 *
 * @since 2016年8月11日
 */
public class RC2Util {

	/**
	 * 加密算法
	 */
	public static final String ALGORITHM = "RC2";

	/**
	 * 密钥长度 
	 */
	public static final int KEY_SIZE = 128;

	/**
	 * @描述：生成密钥
	 * @参数：KEY_CODE
	 * @返回：密钥
	 */
	public static byte[] getKey(String keyCode) {
		try {
			// 实例化密钥生成器
			KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
			// SHA1密码随机数供应者
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(keyCode.getBytes(StandardCharsets.UTF_8));
			// 初始化：AES密钥长度128、192、256位
			kg.init(KEY_SIZE, secureRandom);
			// 生成秘密密钥
			SecretKey secretKey = kg.generateKey();
			// 获得密钥的二进制编码形式
			return secretKey.getEncoded();
		} catch (Exception e) {
			throw new RuntimeException(SecMsg.ERROR_KEYCODE,e);
		}
	}

	/**
	 * @描述：RC2加密
	 * @参数：源数据
	 * @参数：KEY_CODE
	 * @返回：加密数据
	 */
	public static byte[] encode(byte[] data, String keyCode) {
		try {
			// 还原密钥
			SecretKey secretKey = new SecretKeySpec(getKey(keyCode), ALGORITHM);
			// 创建密码器
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			// 初始化密码器，设置为加密模式
			cipher.init(Cipher.ENCRYPT_MODE, secretKey);
			// 加密原数据
			return cipher.doFinal(data);
		} catch (Exception e) {
			throw new RuntimeException(SecMsg.ERROR_KEYCODE,e);
		}
	}

	/**
	 * @描述：RC2解密
	 * @参数：加密数据
	 * @参数：KEY_CODE
	 * @返回：源数据
	 */
	public static byte[] decode(byte[] data, String keyCode) {
		try {
			// 还原为密钥
			SecretKey secretKey = new SecretKeySpec(getKey(keyCode), ALGORITHM);
			// 创建密码器
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			// 初始化密码器，设置为解密模式
			cipher.init(Cipher.DECRYPT_MODE, secretKey);
			// 解密加密数据
			return cipher.doFinal(data);
		} catch (Exception e) {
			throw new RuntimeException(SecMsg.ERROR_KEYCODE,e);
		}
	}

	/**
	 * @描述：RC2加密
	 * @参数：源数据
	 * @参数：KEY_CODE
	 * @返回：加密数据
	 */
	public static String encode(String text, String keyCode) {
        return Base64Util.encodeUrl(encode(text.getBytes(StandardCharsets.UTF_8), keyCode));
    }

	/**
	 * @描述：RC2解密
	 * @参数：加密数据
	 * @参数：KEY_CODE
	 * @返回：源数据
	 */
	public static String decode(String text, String keyCode) {
        return new String(decode(Base64Util.decode(text), keyCode), StandardCharsets.UTF_8);
    }
}
